package com.app.utils.spring.config;

import java.lang.reflect.InvocationTargetException;

/**
 * 服务器系统错误
 */
public class SystemError extends Throwable {

	private static final long serialVersionUID = 1L;
	//错误类型
	private ResultCode retcode = ResultCode.SERVER_ERROR;
	//自定义的错误码
	private String errorCode;

	public SystemError(String errorCode, String message) {
		super(message);
		this.errorCode = errorCode;
	}

	public SystemError(ResultCode retcode, String errorCode, String message) {
		super(message);
		this.retcode = retcode;
		this.errorCode = errorCode;
	}
	
	/**
	 * 自定义错误码
	 */
	public String getErrorCode() {
		return errorCode;
	}

	/**
	 * 返回的状态码
	 */
	public ResultCode getRetcode() {
		return retcode;
	}

	/**
	 * 将异常转化为系统错误
	 */
	public static SystemError exp2Se(Exception e){
		//初始化错误信息和错误码
		String errorCode = "551099";
		String errorMsg  = "系统繁忙，请重试。";
		ResultCode retcode = ResultCode.SERVER_ERROR;
		//判断是否系统异常
		if(e.getCause() instanceof SystemError){
			//系统异常
			SystemError error = (SystemError)e.getCause();
			retcode = error.getRetcode();
			//未定义
			if(error.getRetcode() == ResultCode.NOT_DEFINE){
				errorCode = "551013";
				errorMsg  = "请求未提供或已废弃。";
			}
			//参数异常
			else if(error.getRetcode() == ResultCode.PARAMS_ERROR){
				errorCode = "552001";
				errorMsg  = "请求参数异常，联系管理员。";
			}
			//业务异常
			else if(error.getRetcode() == ResultCode.OTHER){
				errorCode = error.getErrorCode();
				errorMsg  = error.getMessage();
			}
		}
		return new SystemError(retcode, errorCode, errorMsg);
	}
	
	/**
	 * 抛出业务系统错误
	 * @param errorCode 错误码
	 * @param message 错误信息
	 */
	public static void wrapBs(String errorCode, String message){
		SystemError error = new SystemError(ResultCode.OTHER, errorCode, message);
		throw wrapThrow(error);
	}

	/**
	 * 用运行时异常包裹抛出对象，如果抛出对象本身就是运行时异常，则直接返回。
	 * <p>
	 * 如果是 InvocationTargetException，那么将其剥离，只包裹其 TargetException
	 *
	 * @param e
	 *            抛出对象
	 * @return 运行时异常
	 */
	public static RuntimeException wrapThrow(Throwable e) {
		if (e instanceof RuntimeException)
			return (RuntimeException) e;
		if (e instanceof InvocationTargetException)
			return wrapThrow(((InvocationTargetException) e).getTargetException());
		return new RuntimeException(e);
	}
}
